package com.platform.module.admin.aspect;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.platform.module.common.base.BaseReq;
import com.platform.module.common.base.CodeDict;
import com.platform.module.common.base.CommonResp;
import com.platform.module.common.base.NoNeedLogin;
import com.platform.module.common.constant.CacheConstant;
import com.platform.module.common.redis.CacheClient;
import com.platform.module.common.utils.TokenGenerator;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;

@Component
@Aspect
@Order(5)
public class CheckLoginAspect {
    private static final Logger log = LoggerFactory.getLogger(CheckLoginAspect.class);
    @Value("${spring.application.name}")
    private String module;
    @Value("${token.key}")
    private String tokenKey;
    private final HttpServletRequest request;
    private final CacheClient cacheClient;

    public static ThreadLocal<String> userId_TL = new ThreadLocal<>();
    public static ThreadLocal<Long> time_TL = new ThreadLocal<>();
    public static ThreadLocal<String> traceId_TL = new ThreadLocal<>();

    public CheckLoginAspect(CacheClient cacheClient, HttpServletRequest request) {
        this.cacheClient = cacheClient;
        this.request = request;
    }

    @Pointcut("execution(* com.platform.module.admin.controller.*.*(..)) ")
    private void point() {
    }

    @Around("point()")
    public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable {
        try {
            time_TL.set(System.currentTimeMillis());
            traceId_TL.set(UUID.randomUUID().toString().replace("-", ""));
            Method method = ((MethodSignature) pjp.getSignature()).getMethod();
            NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class);
            if (noNeedLogin == null) {
                String accessToken = this.request.getHeader("accessToken");
                if (StringUtils.isNotEmpty(accessToken)) {
                    log.info("request={} accessToken={}", this.request.getRequestURI(), accessToken);
                }

                if (StringUtils.isEmpty(accessToken) || !this.cacheClient.hasKey(CacheConstant.CMS_USER_TOKEN + accessToken)) {
                    return CommonResp.fail(CodeDict.未登录.getCode(), CodeDict.未登录.getMsg());
                }

                Object[] objs = pjp.getArgs();
                String userId = "";

                for (Object obj : objs) {
                    if (obj instanceof BaseReq baseReq) {
                        if (!StringUtils.isBlank(accessToken)) {
                            String[] tt = TokenGenerator.authToken(accessToken, "appId", tokenKey);
                            userId = tt[2];
                            baseReq.setAccessToken(accessToken);
                            baseReq.setAppId(userId);
                        }
                    }
                }

                userId_TL.set(userId);
                this.printReqLog();
            }
        } catch (Exception var11) {
            log.error("异常信息", var11);
        }

        return pjp.proceed();
    }

    private void printReqLog() {
        StringBuilder param = new StringBuilder();
        Map<String, String[]> parameterMap = this.request.getParameterMap();
        parameterMap.forEach((k, v) -> {
            if (StringUtils.isBlank(param.toString())) {
                param.append(" ");
            }
            param.append(k).append(":").append(Arrays.toString(v)).append(" ");
        });
        log.info("userId:{},traceId:{},请求接口:{},参数:{}", userId_TL.get(), traceId_TL.get(), this.request.getRequestURI(), param);
    }

    protected String getHeaderValue() {
        return this.request.getHeader("traceId") == null ? null : this.request.getHeader("traceId");
    }

    @AfterReturning(
            returning = "rvt",
            pointcut = "point()"
    )
    public void methodAfterLog(JoinPoint joinPoint, Object rvt) {
        String traceId = this.getHeaderValue();
        String ret = "";

        try {
            if (rvt == null) {
                log.error("userId:{},traceId:{},返回数据:{}", userId_TL.get(), traceId_TL.get(), ret);
            } else {
                try {
                    JSONObject json = (JSONObject) JSON.toJSON(rvt);
                    if (json != null) {
                        if (json.get("data") != null && json.get("data").toString().length() > 1000) {
                            json.put("data", "simplified log output...");
                        }

                        ret = json.toJSONString();
                    }
                } catch (Exception var6) {
                    ret = String.valueOf(rvt);
                }

                log.info("cost={}ms,userId:{},traceId:{},接口响应:{},返回数据:{}",
                        System.currentTimeMillis() - time_TL.get(), userId_TL.get(), traceId_TL.get(), this.request.getRequestURL(), ret);
            }
        } catch (Exception var7) {
            log.error("异常信息", var7);
            log.error("traceId:{},日志打印出错 返回数据:{}", traceId, ret);
        }

        userId_TL.remove();
        time_TL.remove();
        traceId_TL.remove();
    }
}
